package qf.index;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

public class u5 {

    public static void main(String[] args) throws SQLException, IOException {

//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        System.out.println(format.format(new Date()) + " 程序开始了~~~");
//        String newDataName = "scholar_25_02.";
//        String summaryTable = newDataName + "unified_search_summary_0120";
//        String jiNingMedCollTable = newDataName + "jining_med_coll";
//        String chinaHosp6YearC1RpTable = newDataName + "tb_true_china_hosp_6_year_c1_rp";
//        String orderPmIdAdKwTable = newDataName + "order_pmid_ad_kw";
//        String first5Table = newDataName + "order_name_search_first_5_pmid_list_sum";
//        String pmArticleTable = newDataName + "spider_pubmed_vip_extend";
//        String c11Rp1PmIdTable = newDataName + "c11_rp1_pmid";
//        String pmIdYearC1sRpsTable = newDataName + "pmid_year_c1s_rps";
////        readTable( jiNingMedCollTable, "pid", "C1`,`RP`,`PM`,`PY");
//
//        // 获取中国医院的发文，并存表，上线时只需要使用保存下来的chinaHosp6YearC1RpTable表的数据。
//        String limit = "";
////        String limit = " limit 1";
////        getPmIdYearInfoSet(jiNingMedCollTable, "pid", "pmId`,`year`,`c1_au`,`rp_au", chinaHosp6YearC1RpTable, c11Rp1PmIdTable);
//
//        Set<En.PmIdYearInfo> pmIdYearInfoSet = getPmIdYearInfoSet(jiNingMedCollTable, "pid", "pmId`,`year`,`c1_au`,`rp_au", limit, pmIdYearC1sRpsTable);
//
//
//        // 从表中把中国医院的发文数据提取出来保存到searchList中，如果上线使用的话，此searchList需要永驻内存。
//        En.SearchSet searchSet = new En.SearchSet();
//        searchSet.setC1(1);
//        searchSet.setRp(0);
//        searchSet.setAndOrOr(1);
////        private int c1 = 1; // 只要第一作者，为1，默认为1，全部都要为0
////        private int rp = 1; // 只要第一通讯作者，为1，默认为1，全部都要为0
////        private int andOrOr = 1; // 作者和通讯之间的关系，默认为OR，为1，意思是作者是可以，通讯是也可以，两个都要（即两个都要满足为0）。
//        searchSet.getYearList().add(2019);
//        searchSet.getYearList().add(2020);
//        searchSet.getYearList().add(2021);
//        searchSet.getYearList().add(2022);
//        searchSet.getYearList().add(2023);
//        searchSet.getYearList().add(2024);
//        searchSet.getYearList().add(2025);
//        Set<Integer> yearSet = new HashSet<>(searchSet.getYearList());
//        System.out.println("rp:" + searchSet.getRp() + " c1:" + searchSet.getC1() + " andOrOr:" + searchSet.getAndOrOr() + " yearSet:" + searchSet.getYearList());
////
//        Set<En.PmIdYearInfo> pmIdYearInfos = readPmIdYearInfoSet(pmIdYearC1sRpsTable, "id", "info");
////        // 检索测试
//        Map<Integer, String> orderAndInfoMap = getOrderAndInfoMap();
//        Db.use().execute("truncate table " + orderPmIdAdKwTable);
//        for (Map.Entry<Integer, String> entry : orderAndInfoMap.entrySet()) {
//            System.out.println(format.format(new Date()) + " order: " + entry.getKey());
//            doSearch(entry.getValue(), pmIdYearInfos, yearSet, orderPmIdAdKwTable, entry.getKey(), 0, 0, 1);
//            doSearch(entry.getValue(), pmIdYearInfos, yearSet, orderPmIdAdKwTable, entry.getKey(), 1, 1, 1);
//            doSearch(entry.getValue(), pmIdYearInfos, yearSet, orderPmIdAdKwTable, entry.getKey(), 0, 0, 0);
//            doSearch(entry.getValue(), pmIdYearInfos, yearSet, orderPmIdAdKwTable, entry.getKey(), 1, 1, 0);
//            doSearch(entry.getValue(), pmIdYearInfos, yearSet, orderPmIdAdKwTable, entry.getKey(), 1, 0, 1);
//        }
//
//        Map<Integer, byte[]> pmIdAndAdListMap = ReadAd.getPmIdAndAdListMap(pmArticleTable, "id", "pmid`,`author_extend", limit);
//        System.out.println("pmIdAndAdListMap.size(): " + pmIdAndAdListMap.size());
//        ReadAd.updateOrderPmIdAdKwTable(orderPmIdAdKwTable, "id", "pmid`,`ut_c1", pmIdAndAdListMap);
//
//        insertFirst5Table(orderPmIdAdKwTable, "id", "pm_ad`,`order`,`pmid", first5Table);


// main
    }

    public static Set<En.PmIdYearInfo> readPmIdYearInfoSet(String pmIdYearC1sRpsTable, String autoId, String field) throws SQLException {
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + pmIdYearC1sRpsTable);
        Set<En.PmIdYearInfo> pmIdYearInfoSet = new ConcurrentHashSet<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + pmIdYearC1sRpsTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + pmIdYearC1sRpsTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                for (Entity entry : tableData) {
                    String info = entry.getStr("info");
                    if (null != info && info.contains("c1List")) {
                        En.PmIdYearInfo pmIdYearInfo = JSONObject.parseObject(info, En.PmIdYearInfo.class);
                        pmIdYearInfoSet.add(pmIdYearInfo);
                    }
                }
            }
        }
        return pmIdYearInfoSet;
    }

    public static void readTable(String jiNingMedCollTable, String autoId, String field) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + jiNingMedCollTable);
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + jiNingMedCollTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + jiNingMedCollTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                for (Entity entry : tableData) {
                    List<En.C1Auth> c1List = Utils.getC1List(entry.getStr("C1"));
                    List<En.C1Auth> rpList = Utils.getRpList(entry.getStr("RP"));
                    List<En.C1Auth> rpChangeC1 = ChangeRp.rpChangeC1(c1List, rpList);
                    String pm = Utils.getStrField(entry, "PM");
                    int pmId = NumberUtil.isInteger(pm) ? Integer.parseInt(pm.trim()) : 0;
                    String py = Utils.getStrField(entry, "PY");
                    int year = NumberUtil.isInteger(py) ? Integer.parseInt(py.trim()) : 1900;
                    int id = Utils.getIntField(entry, autoId);
                    try {
                        Db.use().update(
                                Entity.create().set("pmId", pmId).set("c1_au", JSONUtil.toJsonStr(c1List)).set("rp_au", JSONUtil.toJsonStr(rpChangeC1)).set("year", year),
                                Entity.create(jiNingMedCollTable).set(autoId, id));
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void insertFirst5Table(String orderPmIdAdKwTable, String autoId, String field, String first5Table) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + orderPmIdAdKwTable);
        Map<Integer, Map<String, Integer>> orderWordSumMap = new ConcurrentHashMap<>();
        Map<Integer, Set<Integer>> orderPmIdSetMap = new ConcurrentHashMap<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + orderPmIdAdKwTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + orderPmIdAdKwTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + orderPmIdAdKwTable + Utils.printMemoryStr() + "\033[0m");
                for (Entity entry : tableData) {
                    String pmAd = Utils.getStrField(entry, "pm_ad");
                    int order = Utils.getIntField(entry, "order");
                    int pmId = Utils.getIntField(entry, "pmid");
                    if (order > 0 && pmId > 0) {
                        if (pmAd.length() > 8) {
                            String[] split = pmAd.split(", ");
                            for (String s : split) {
                                s = s.trim().replace("People's Republic of China", "China");
                                if (s.contains(" ") && !Pattern.compile("[0-9]{4,6}").matcher(s).find() && !s.contains("Department") && !s.contains("Key Laboratory")) {
                                    Utils.putIntStrIntSum(order, s, orderWordSumMap);
                                }
                            }
                        }
                        Utils.putIntSetIntMap(orderPmIdSetMap, order, pmId);
                    }
                }
            }
        }
        Db.use().execute("truncate table " + first5Table);
        List<String> list = FileUtil.readLines("C:\\临时文件\\2025_02\\temp_order_name_search.txt", "utf-8");
        for (String s : list) {
            String[] split = s.split("_");
            if (split.length == 3 && NumberUtil.isInteger(split[0])) {
                int order = Integer.parseInt(split[0]);
                Map<String, Integer> first5Map = new HashMap<>();
                if (orderWordSumMap.containsKey(order)) {
                    first5Map = Utils.mapSortValueIntLen(orderWordSumMap.get(order), 6);
                }
                Set<Integer> pmIdSet = orderPmIdSetMap.containsKey(order) ? orderPmIdSetMap.get(order) : new HashSet<>();
                try {
                    Db.use().insert(Entity.create(first5Table).set("order", order).set("name", split[1]).set("search", split[2]).set("sum", pmIdSet.size())
                            .set("firsr_5_word", JSONUtil.toJsonStr(first5Map)).set("pmid_list", JSONUtil.toJsonStr(pmIdSet)));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static Set<En.PmIdYearInfo> getPmIdYearInfoSet(String summaryOldTable, String autoId, String field, String limit, String pmIdYearC1sRpsTable) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        Set<En.PmIdYearInfo> pmIdYearInfoSet = new ConcurrentHashSet<>();
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + summaryOldTable);
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + summaryOldTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + summaryOldTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + summaryOldTable + Utils.printMemoryStr() + "\033[0m");
                    for (Entity entry : tableData) {
                        Integer pmId = entry.getInt("pmId");
                        Integer year = entry.getInt("year");
                        if (null != year && year > 2018 && null != pmId && pmId > 0) {
                            String c1Au = Utils.getStrField(entry, "c1_au");
                            String rpAu = Utils.getStrField(entry, "rp_au");
                            List<En.C1Auth> c1List = (c1Au.contains("sort")) ? JSONObject.parseArray(c1Au, En.C1Auth.class) : new ArrayList<>();
                            List<En.C1Auth> rpList = (rpAu.contains("sort")) ? JSONObject.parseArray(rpAu, En.C1Auth.class) : new ArrayList<>();
                            En.PmIdYearInfo pmIdYearInfo = new En.PmIdYearInfo();
                            List<String> c1s = new ArrayList<>();
                            for (En.C1Auth c1Auth : c1List) {
                                c1s.add(c1Auth.getInfo());
                            }
                            List<String> rps = new ArrayList<>();
                            for (En.C1Auth c1Auth : rpList) {
                                rps.add(c1Auth.getInfo());
                            }
                            pmIdYearInfo.setYear(year);
                            pmIdYearInfo.setPmId(pmId);
                            pmIdYearInfo.setC1List(c1s);
                            pmIdYearInfo.setRpList(rps);
                            if (!pmIdYearInfoSet.contains(pmIdYearInfo)) {
                                try {
                                    Db.use().insert(Entity.create(pmIdYearC1sRpsTable).set("info", JSONUtil.toJsonStr(pmIdYearInfo)));
                                    pmIdYearInfoSet.add(pmIdYearInfo);
                                } catch (SQLException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                } catch (SQLException e) {
//                    throw new RuntimeException(e);
                }
            });
        }
        return pmIdYearInfoSet;
    }

    public static Map<Integer, String> getOrderAndInfoMap() {
        String filePath = "C:\\临时文件\\2025_02\\temp_hosp.txt";
        Map<Integer, String> orderAndInfoMap = new HashMap<>();
        List<String> pathList = FileUtil.readLines(filePath, "utf-8");
        for (String s : pathList) {
            String[] split = s.split("_");
            if (split.length == 2 && NumberUtil.isInteger(split[0]) && split[1].contains("=")) {
                orderAndInfoMap.put(Integer.parseInt(split[0]), split[1]);
            }
        }
        return orderAndInfoMap;
    }

    public static String isChinaHosp(String c1Au, Set<String> nameSet, Set<String> hospSet, Set<String> removeSet, Set<String> c1OrRpSet, Map<String, Integer> c1OrRpSortMap) {
        if (null == c1Au || !c1Au.contains("sort")) {
            return "";
        }
        List<En.C1Auth> c1List = JSONObject.parseArray(c1Au, En.C1Auth.class);
        for (En.C1Auth c1Auth : c1List) {
            String info = ("".equals(c1Auth.getInfo()) ? c1Auth.getFull() : c1Auth.getInfo()).replace("ETH, Zurich", "ETH Zurich").toLowerCase().trim();
            String[] split = info.replace(";", ", ").replace(". ", ", ").split(",");
            boolean isChina = info.contains("pr china") || info.contains("peoples r china") || info.contains("republic of china") || info.contains("p. r. china") || info.contains("people's republic of china") ||
                    info.contains("petrochina") || info.contains("westchina") || info.contains("chinamed") || info.contains("immunochina") || info.contains("chinajapan") || info.contains("powerchina") ||
                    info.contains("southchina") || info.contains("eastchina") || info.contains("chinathree") || info.contains("china570311") || info.contains("china450000") || info.contains("china733000");
            for (String c : split) {
                c = c.replaceAll(" +", " ").trim();
                if (!isChina) {
                    for (String n : nameSet) {
                        if (n.equals(c) || c.contains(" " + n + " ") || c.startsWith(n + " ") || c.endsWith(" " + n)) {
                            isChina = true;
                            break;
                        }
                    }
                }
                if (isChina) {
                    if (Unit.isHosp(info, hospSet, removeSet)) {
                        int sort = c1Auth.getSort();
                        c1OrRpSortMap.put(info, sort);
                        c1OrRpSet.add(info);
                    }
                }
            }
        }
        return !c1List.isEmpty() ? c1List.get(0).getInfo() : "";
    }

    public static String dellEnd(String s) {
        s = s.trim();
        return s.endsWith(".") ? s.substring(0, s.length() - 1).trim() : s.trim();
    }

    public static void doSearch(String kw, Set<En.PmIdYearInfo> pmIdYearInfoSet, Set<Integer> yearSet, String orderPmIdAdKwTable, int order, int c1, int rp, int andOrOr) {
        pmIdYearInfoSet.parallelStream().forEach(pmIdYearInfo -> {
            int year = pmIdYearInfo.getYear();
            int pmId = pmIdYearInfo.getPmId();
            if (yearSet.contains(year)) {
                List<String> c1SumList = getSum(pmIdYearInfo.getC1List(), kw, c1);
                List<String> rpSumList = getSum(pmIdYearInfo.getRpList(), kw, rp);
//        private int c1 = 1; // 只要第一作者，为1，默认为1，全部都要为0
//        private int rp = 1; // 只要第一通讯作者，为1，默认为1，全部都要为0
//        private int andOrOr = 1; // 作者和通讯之间的关系，默认为OR，为1，意思是作者是可以，通讯是也可以，两个都要（即两个都要满足为0）。
                boolean result = false;
                if (andOrOr == 1) {
                    if (!c1SumList.isEmpty() || !rpSumList.isEmpty()) {
                        result = true;
                    }
                } else {
                    if (!c1SumList.isEmpty() && !rpSumList.isEmpty()) {
                        result = true;
                    }
                }
                if (result) {
                    try {
                        Db.use().insert(Entity.create(orderPmIdAdKwTable).set("order", order).set("ut_c1", JSONUtil.toJsonStr(c1SumList)).set("ut_rp", JSONUtil.toJsonStr(rpSumList)).set("pmid", pmId).set("kw", kw).set("type", (Integer.toString(c1) + rp + andOrOr)));
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public static List<String> getSum(List<String> c1List, String kw, int c1) {
        List<String> rList = new ArrayList<>();
        for (String info : c1List) {
            if (AdSearch.doCheck(info, AdSearch.checkGrammar(kw))) {
                rList.add(info);
            }
            if (c1 == 1) {
                return rList;
            }
        }
        return rList;
    }

    public static Set<Integer> addPidSet(List<En.PidSort> pidSortList, Set<Integer> yearSet, int rp, int c1, int andOrOr) {
        Set<Integer> set = new HashSet<>();
        for (En.PidSort pidSort : pidSortList) {
            List<Integer> sortList = pidSort.getSortList();
            int py = pidSort.getPy();
            int pid = pidSort.getPid();
            if (yearSet.contains(py)) {
                if (sortList.size() == 2) {
//        private int c1 = 1; // 只要第一作者，为1，默认为1，全部都要为0
//        private int rp = 1; // 只要第一通讯作者，为1，默认为1，全部都要为0
//        private int andOrOr = 1; // 作者和通讯之间的关系，默认为OR，为1，意思是作者是可以，通讯是也可以，两个都要（即两个都要满足为0）。
                    int isC1 = c1 == 1 && sortList.get(0).equals(1) ? 1 : 0;
                    isC1 = c1 != 1 && !sortList.get(0).equals(0) ? 1 : isC1;
                    int isRp = rp == 1 && sortList.get(1).equals(1) ? 1 : 0;
                    isRp = rp != 1 && !sortList.get(1).equals(0) ? 1 : isRp;
                    int isAndOrOr = andOrOr == 1 && (isC1 + isRp > 0) ? 1 : 0;
                    isAndOrOr = andOrOr != 1 && (isC1 + isRp > 1) ? 1 : isAndOrOr;
                    if (isAndOrOr > 0) {
                        set.add(pid);
                    }
                }
            }
        }
        return set;
    }

    public static List<En.SearchList> getSearchList(String chinaHosp6YearC1RpTable, String autoId, String field) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 10000;
        String limit = "";
//        String limit = " limit 1";
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + chinaHosp6YearC1RpTable);
        List<En.SearchList> searchList = new ArrayList<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + chinaHosp6YearC1RpTable).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            for (Integer startId : tableList) {
                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + chinaHosp6YearC1RpTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
//                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + chinaHosp6YearC1RpTable + Utils.printMemoryStr() + "\033[0m");
                for (Entity entry : tableData) {
                    String c1Rp = entry.getStr("c1_rp");
                    String pidPySort = entry.getStr("pid_py_sort");
                    if (null != c1Rp && null != pidPySort && c1Rp.length() > 3 && pidPySort.contains("sortList")) {
                        List<En.PidSort> pidSortList = JSONObject.parseArray(pidPySort, En.PidSort.class);
                        En.SearchList search = new En.SearchList();
                        search.setInfo(c1Rp.toLowerCase());
                        search.setPidSorts(pidSortList);
                        searchList.add(search);
                    }
                }
            }
        }
        return searchList;
    }

    public static void putMap(String str, En.PidSort pidSort, Map<String, Set<En.PidSort>> c1OrRpPidSortMap) {
        c1OrRpPidSortMap.compute(str, (k, v) -> {
            if (v == null) {
                v = new ConcurrentHashSet<>();
            }
            v.add(pidSort);
            return v;
        });
    }


}
